home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1999 January
/
EnigmA AMIGA RUN 33 (1999)(G.R. Edizioni)(IT)[!][issue 1999-01].iso
/
earcd
/
apus
/
boothack
/
old
/
bh980726.lha
/
bh980726-2
/
ppc_boot.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-02-22
|
7KB
|
364 lines
/****************************************************************************
* ppc_boot.c -- This program initializes the PPC on a Phase5 PowerUp board
* and boots the kernel.
*
* Copyright 1997, 1998 by Jesper Skov (jskov@cygnus.co.uk)
***************************************************************************/
#define SYMBOL_NAME_STR(X) #X
#define INTENA 0xdff09a
#define INTREQ 0xdff09c
#define CHIP_PTR (0xfff00)
#define REG_SHADOW (0xf60018)
#define REGSHADOW_SETRESET (0x80)
#define REGSHADOW_SHADOW (0x01)
#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/memory.h>
#include <powerup/ppclib/interface.h>
#include <powerup/gcclib/powerup_protos.h>
void goSupervisor(void);
void relocate(void);
extern char relocateEnd;
void progress_init (void);
void progress (char);
unsigned int main(void)
{
int i;
unsigned long *s, *d;
unsigned long ptr;
register unsigned long r0 __asm("r0");
register unsigned long r3 __asm("r3");
progress_init ();
progress ('a');
{
/* Wait for the m68k to complete its business (shutting up
* boards).
* It would be better to do proper synchronization, but my
* attempts to do something "nice" failed. I think it's
* because the m68k drops everything on the floor when it
* attempts to write the same address the PPC is polling.
* The PPC uKernel could be used to send a signal, but then
* there's no way to be sure "where" the m68k is when the
* PPC disables interrupts. Therefore this loop for now.
*/
int fingers_crossed = 1;
for (i = 0; i < 1000000;i++);
}
progress ('b');
{
unsigned short* intena_p = (unsigned short*) INTENA;
unsigned short* intreq_p = (unsigned short*) INTREQ;
/* Disable IRQs. */
*intena_p = 0x7fff;
*intreq_p = 0x7fff;
}
progress ('c');
/* Get the PR bit set. */
goSupervisor();
progress ('d');
PPCCacheFlushAll();
__asm __volatile (
/* Disable caches. */
"mfspr 0,1008 \n\t" /* HID0 */
"lis 3,0 \n\t"
"ori 3,3,0xc000 \n\t" /* HID0_ICE|HID0_DCE */
"andc 0,0,3 \n\t"
"sync \n\t"
"isync \n\t"
"mtspr 1008,0 \n\t" /* HID0 */
/* Disable address translation. */
"mfmsr 0 \n\t"
"li 3,0b110000 \n\t" /* MSR_IR|MSR_DR */
"andc 0,0,3 \n\t"
"isync \n\t"
"mtmsr 0 \n\t"
"sync \n\t"
:: "r" (r0), "r" (r3));
/* I don't know if this works so it is disabled until someone with a
blizzard verifies the effect. mm/init.c will need to be adjusted
if this code is activated (init makes presumptions about
shadowing based on memory size). */
#if 0
{
unsigned char* reg_shadow = (unsigned char*) REG_SHADOW;
*reg_shadow = (REGSHADOW_SETRESET | REGSHADOW_SHADOW);
}
#endif
progress ('e');
/* Get info-ptr from CHIP_PTR.
* Relocate code to memory just above info.
*/
ptr = (unsigned long) *((unsigned long*) CHIP_PTR);
ptr += 0x0200;
ptr = ptr + 4 - (ptr % 4);
s = (unsigned long*) &relocate;
d = (unsigned long*) ptr;
for(i = (((unsigned long)&relocateEnd) - ((unsigned long)s))/4;
i >= 0; i--){
*d = *s;
d++;
s++;
}
progress ('f');
/* Jump to relocated code. */
r0 = ptr;
__asm __volatile (
"mtlr 0 \n\t"
"blr \n\t"
: /* no outputs */
: "r" (r0), "r" (r3)
/* no return */);
/* fake a noreturn */
for (;;);
return;
}
void relocate(void)
{
const unsigned long *info;
unsigned char *s, *d, *e;
progress ('g');
/* Get info-ptr from CHIP_PTR. */
info = (const unsigned long*) *((unsigned long*) CHIP_PTR);
/* Verify checksum. */
if (info[7])
{
int i = (info[2] + info[3]) / 4;
unsigned char* k_p = (unsigned char*) info[0];
unsigned long kcs = 0;
while (i--)
{
unsigned long w = 0;
w |= *k_p++;
w <<= 8;
w |= *k_p++;
w <<= 8;
w |= *k_p++;
w <<= 8;
w |= *k_p++;
kcs = kcs ^ i;
kcs = kcs ^ w;
}
progress ('C');
progress ('1');
if (info[7] == kcs)
progress ('+');
else
progress ('-');
}
/* Copy kernel to memstart */
s = (unsigned char *) info[0];
d = (unsigned char *) info[1];
e = (unsigned char *) (info[1] + info[2] + info[3]);
while(d != e){
*d = *s;
s++;
d++;
}
progress ('h');
/* Verify checksum. */
if (info[7])
{
int i = (info[2] + info[3]) / 4;
unsigned char* k_p = (unsigned char*) info[1];
unsigned long kcs = 0;
while (i--)
{
unsigned long w = 0;
w |= *k_p++;
w <<= 8;
w |= *k_p++;
w <<= 8;
w |= *k_p++;
w <<= 8;
w |= *k_p++;
kcs = kcs ^ i;
kcs = kcs ^ w;
}
progress ('C');
progress ('2');
if (info[7] == kcs)
progress ('+');
else
progress ('-');
}
/* Copy ramdisk to memory end. */
d = (unsigned char *) info[1] + info[5];
e = d - info[4];
s = s + info[4];
while(d != e){
s--;
d--;
*d = *s;
}
progress ('i');
/* Let 0xfff00000 contain sum used for VTOP/PTOV in head.S. */
/* Also put it at kernel start since kernel copies the vectors
* to their proper location after modifying a few instructions.
*/
#define KERNELBASE 0xC0000000
*((unsigned long *)0xfff00000) = info[1] - KERNELBASE;
*((unsigned long *) info[1]) = info[1] - KERNELBASE;
progress ('K');
{
register unsigned long r3 __asm("r3");
register unsigned long r4 __asm("r4");
register unsigned long r5 __asm("r5");
register unsigned long r6 __asm("r6");
register unsigned long r7 __asm("r7");
/* initrd pointers (virtual addresses) */
if (info[4]){
/* end of rd */
r5 = info[5] + KERNELBASE;
/* start of rd */
r4 = r5 - info[4];
} else
r4 = 0;
/* Make it easy to identify APUS in identify_machine. */
r3 = 0x61707573;
/* Jump to kernel start. */
r7 = info[1] + 0xc;
__asm __volatile (
"mtlr 7 \n\t"
"blr \n\t"
: /* no outputs */
: "r" (r3), "r" (r4), "r" (r5), "r" (r6), "r" (r7)
/* no return */);
}
/* fake a noreturn */
for (;;);
}
/* Play that jive... */
extern char setPR, setPRend;
void goSupervisor(void)
{
unsigned long *s, *d;
int len = ((int) &setPRend - (int) &setPR) / 4;
/* Copy code to TRAP entry */
d = (unsigned long*) 0xfff00700;
s = (unsigned long*) &setPR;
for(;len > 0;len--){
*d = *s;
d++;
s++;
}
PPCCacheFlushAll();
/* Execute code */
__asm__ (
"trap \n\t"
);
}
void progress_init (void)
{
const unsigned long *info;
unsigned long *mesg_base;
unsigned long* p;
info = (const unsigned long*) *((unsigned long*) CHIP_PTR);
mesg_base = (unsigned long*) info[6];
p = mesg_base;
*p++ = 'SAVE';
*p++ = 'BOOT';
*p++ = (unsigned long) mesg_base;
*p++ = 0;
}
void progress (char c)
{
const unsigned long *info;
char progress_state;
char* progress_ptr;
unsigned long* mesg_base;
info = (const unsigned long*) *((unsigned long*) CHIP_PTR);
mesg_base = (unsigned long*) info[6];
progress_ptr = mesg_base[3] + (char*)&mesg_base[4];
*progress_ptr = c;
mesg_base[3]++;
}
asm(
".text\n"
".align 4\n"
SYMBOL_NAME_STR(setPR) ":
/* Increase the return EA so we get to the next instruction */
mtsprg 1,1
mfsrr0 1
addi 1,1,4
mtsrr0 1
mfsprg 1,1
/* Fiddle the PR bit */
mfsrr1 0
rlwinm 0,0,0,18,16
mtsrr1 0
rfi
"
SYMBOL_NAME_STR(setPRend) ":
");
asm(
".text\n"
".align 4\n"
SYMBOL_NAME_STR(relocateEnd) ":
nop
"
);